#include "MyQueue.h"
#include <stdio.h>
#include <stdlib.h>

/**
 * 初始化队列
 * @param capacity 队列的容量
 * @return 创建好的队列
 */
struct MyQueue * MyQueue_init(const int capacity) {
    if (capacity <= 0) {
        fprintf(stderr, "The queue capacity must be greater than 0!\n");
        exit(EXIT_FAILURE);
    }
    struct MyQueue * p_queue = (struct MyQueue *) malloc(sizeof(struct MyQueue));
    if (!p_queue) {
        perror("MyQueue init failure");
        exit(EXIT_FAILURE);
    }
    int * p_array = (int *) malloc(sizeof(int) * capacity);
    if (!p_array) {
        perror("MyQueue array init failure");
        free(p_queue);
        p_queue = NULL;
        exit(EXIT_FAILURE);
    }
    p_queue -> front = 0;
    p_queue -> rear = 0;
    p_queue -> capacity = capacity;
    p_queue -> array = p_array;
    return p_queue;
}

/**
 * 入队
 * @param p_queue 待放入元素的队列
 * @param element 入队的元素
 */
void MyQueue_enQueue(struct MyQueue * p_queue, const int element) {
    if ((p_queue -> rear + 1) % p_queue -> capacity == p_queue -> front) {
        fprintf(stderr, "Queue Full!\n");
        MyQueue_deinit(p_queue);
        exit(EXIT_FAILURE);
    }
    p_queue -> array[p_queue -> rear] = element;
    p_queue -> rear = (p_queue -> rear + 1) % p_queue -> capacity;
}

/**
 * 出队
 * @param p_queue 待出队元素的队列
 * @return 出队的元素
 */
int MyQueue_deQueue(struct MyQueue * p_queue) {
    if (p_queue -> rear == p_queue -> front) {
        fprintf(stderr, "Queue Empty!\n");
        MyQueue_deinit(p_queue);
        exit(EXIT_FAILURE);
    }
    int deQueueElement = p_queue -> array[p_queue -> front];
    p_queue -> front = (p_queue -> front + 1) % p_queue -> capacity;
    return deQueueElement;
}

/**
 * 输出队列
 * @param p_queue 待输出元素的队列
 */
void MyQueue_output(const struct MyQueue * const p_queue) {
    int i = p_queue -> front, tmp = 0;
    printf("[");
    for (; i != p_queue -> rear; i = tmp) {
        printf("%d", p_queue -> array[i]);
        tmp = (i + 1) % p_queue -> capacity;
        if (tmp != p_queue -> rear) {
            printf(", ");
        }
    }
    printf("]\n");
}

/**
 * 释放队列
 * @param p_queue 待释放的队列
 */
void MyQueue_deinit(struct MyQueue * p_queue) {
    free(p_queue -> array);
    p_queue -> array = NULL;
    p_queue -> front = 0;
    p_queue -> rear = 0;
    free(p_queue);
    p_queue = NULL;
}
